package org.cjstudio.holypoopsgrs_protytpe.resource;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.cjstudio.holypoopsgrs_protytpe.resource.Resources.Scoreboard.ScoreEntry;
import org.cjstudio.holypoopsgrs_protytpe.resource.Resources.UserProfileBook.UserProfile;


public class Resources {
	
	/**_ID_**///Long
	/**_RANK_**///Long
	/**_SCORE_**///Integer
	/**_DATE_**///Date
	/**_SCORE_ENTRY_**///ScoreEntry
	/**_KEY_**///String
	/**_NAME_**///String
	/**_MESSAGE_**///String
	/**_USER_PROFILE_**///UserProfile
	
	public static class Scoreboard {
		//DB Schema : (id, score, scoreDate)
		private static abstract class ScoreEntrySchema<_ID_, _SCORE_, _DATE_, _RANK_> {
			protected _ID_ id;
			protected _SCORE_ score;
			protected _DATE_ scoreDate;

			protected _RANK_ rank;
		}
		private static abstract class ScoreEntryTemplate<_ID_, _SCORE_, _DATE_, _RANK_> extends ScoreEntrySchema<_ID_, _SCORE_, _DATE_, _RANK_> {
//			/* TEST TOOL
			public void setId(_ID_ id) {
				this.id = id;
			}
//			*/
			public _ID_ getId() {
				return id;
			}
			public void setScore(_SCORE_ score) {
				this.score = score;
			}
			public _SCORE_ getScore() {
				return score;
			}
			public void setScoreDate(_DATE_ scoreDate) {
				this.scoreDate = scoreDate;
			}
			public _DATE_ getScoreDate() {
				return scoreDate;
			}
			public void setRank(_RANK_ rank) {
				this.rank  = rank;
			}
			public _RANK_ getRank() {
				return rank;
			}
		}
		public static abstract class ScoreEntry  extends ScoreEntryTemplate <
			/**_ID_**/Long,
			/**_SCORE_**/Integer,
			/**_DATE_**/Date,
			
			/**_RANK_**/Long
		> { }
		
		private static interface ScoreboardResourceInterface<_ID_, _SCORE_, _SCORE_ENTRY_> {
			public void updateScore(_ID_ id, _SCORE_ score);
			public _SCORE_ENTRY_ getScoreEntry(_ID_ id);
			public _SCORE_ENTRY_ getRankedScoreEntry(_ID_ id);
			public _SCORE_ENTRY_ updateScoreThenGetRankedScoreEntry(_ID_ id, _SCORE_ score);
			public List<_SCORE_ENTRY_> getScoreEntriesInRange(int start, int end);
			public List<_SCORE_ENTRY_> getLeaderEntries(int limit);
		}
		public static abstract class ScoreboardResource implements ScoreboardResourceInterface<
			/**_ID_**/Long, 
			/**_SCORE_**/Integer, 
			/**_SCORE_ENTRY_**/ScoreEntry
		> { }
	}
	
	public static class UserProfileBook {
		private static abstract class UserProfileSchema<_KEY_, _ID_, _NAME_, _MESSAGE_> {
//			protected _KEY_ key;
			protected _ID_ id;
			protected _NAME_ name;
			protected _MESSAGE_ message;
		}
		private static abstract class UserProfileTemplate<_KEY_, _ID_, _NAME_, _MESSAGE_> extends UserProfileSchema<_KEY_, _ID_, _NAME_, _MESSAGE_> {
			/*
			public void setKey(_KEY_ key) {
				this.key = key;
			}
			public _KEY_ getKey() {
				return key;
			}
			*/
			public void setId(_ID_ id) {
				this.id = id;
			}
			public _ID_ getId() {
				return id;
			}
			public void setName(_NAME_ name) {
				this.name = name;
			}
			public _NAME_ getName() {
				return name;
			}
			public void setMessage(_MESSAGE_ message) {
				this.message = message;
			}
			public _MESSAGE_ getMessage() {
				return message;
			}
		}
		public static abstract class UserProfile extends UserProfileTemplate<
			/**_KEY_**/String, 
			/**_ID_**/Long, 
			/**_NAME_**/String, 
			/**_MESSAGE_**/String
		> { }
		
		private static interface UserProfileResourceInterface<_KEY_, _ID_, _NAME_, _USER_PROFILE_> {
			public _ID_ getUserId(_KEY_ key);
			public void setName(_ID_ id, _NAME_ name);
			public _USER_PROFILE_ getUserProfile(_ID_ id);
			public _USER_PROFILE_ setNameThenGetUserProfile(_ID_ id, _NAME_ name);
			public _USER_PROFILE_ getUserProfileByKey(_KEY_ key);
			public Map<_ID_, _USER_PROFILE_> getUserProfiles(List<_ID_> ids);
		}
		public static abstract class UserProfileResource implements UserProfileResourceInterface<
			/**_KEY_**/String, 
			/**_ID_**/Long, 
			/**_NAME_**/String, 
			/**_USER_PROFILE_**/UserProfile
		> { }
	}
	

	public static class HolyPoopsResources {
		public static abstract class LeaderboardSchema<_TYPE_, _ENTRY_, _DATE_> {
			protected _TYPE_ type;
			protected List<_ENTRY_> entries;
			protected _DATE_ leaderboardDate;
		}
		public static abstract class LeaderboardTemplate<_TYPE_, _ENTRY_, _DATE_> extends LeaderboardSchema<_TYPE_, _ENTRY_, _DATE_> {
			public void setType(_TYPE_ type) {
				this.type = type;
			}
			public _TYPE_ getType() {
				return type;
			}
			public void setEntries(List<_ENTRY_> entries) {
				this.entries = entries;
			}
			public List<_ENTRY_> getEntries() {
				return entries;
			}
			public void setLeaderboardDate(_DATE_ leaderboardDate) {
				this.leaderboardDate = leaderboardDate;
			}
			public _DATE_ getLeaderboardDate() {
				return leaderboardDate;
			}
		}
		
		public static abstract class LeaderboardEntrySchema<_RANK_, _NAME_, _MESSAGE_, _SCORE_, _DATE_> {
			public _RANK_ rank;
			public _NAME_ name;
			public _MESSAGE_ message;
			public _SCORE_ highest;
			public _DATE_ highestDate;
		}
		public static abstract class LeaderboardEntryTemplate<_RANK_, _NAME_, _MESSAGE_, _SCORE_, _DATE_> extends LeaderboardEntrySchema<_RANK_, _NAME_, _MESSAGE_, _SCORE_, _DATE_> {
			public void setRank(_RANK_ rank) {
				this.rank = rank;
			}
			public _RANK_ getRank() {
				return rank;
			}
			public void setName(_NAME_ name) {
				this.name = name;
			}
			public _NAME_ getName() {
				return name;
			}
			public void setMessage(_MESSAGE_ message) {
				this.message = message;
			}
			public _MESSAGE_ getMessage() {
				return message;
			}
			public void setHighest(_SCORE_ highest) {
				this.highest = highest;
			}
			public _SCORE_ getHighest() {
				return highest;
			}
			public void setHighestDate(_DATE_ highestDate) {
				this.highestDate = highestDate;
			}
			public _DATE_ getHighestDate() {
				return highestDate;
			}
		}
		public static class LeaderboardEntry extends LeaderboardEntryTemplate<
			/**_RANK_**/Long, 
			/**_NAME_**/String, 
			/**_MESSAGE_**/String, 
			/**_SCORE_**/Integer,
			/**_DATE_**/Date
		> {
			public LeaderboardEntry(ScoreEntry entry, UserProfile profile) {
				this.rank = entry.rank;
				this.name = profile.name;
				this.message = profile.message;
				this.highest = entry.score;
				this.highestDate = entry.scoreDate;
			}
		}
		
		public static class Leaderboard extends LeaderboardTemplate<
			/**_TYPE_**/String, 
			/**_ENTRY_**/LeaderboardEntry, 
			/**_DATE_**/Date
		> {
			public Leaderboard(String type, List<ScoreEntry> entries, Map<Long, UserProfile> profiles) {
				this.type = type;
				this.entries = new ArrayList<LeaderboardEntry>();
				for(int i=0; i<entries.size(); i++) {
					LeaderboardEntry entry = new LeaderboardEntry(entries.get(i), profiles.get(entries.get(i).id));
					this.entries.add(entry);
				}
			}
		}
		
		public static abstract class PersonalRecordSchema<_NAME_, _RANK_, _SCORE_, _DATE_> {
			protected _NAME_ name;
			protected _RANK_ rank;
			protected _SCORE_ highest;
			protected _DATE_ highestDate;
		}
		public static abstract class PersonalRecordTemplate<_NAME_, _RANK_, _SCORE_, _DATE_> extends PersonalRecordSchema<_NAME_, _RANK_, _SCORE_, _DATE_> {
			public void setName(_NAME_ name) {
				this.name = name;
			}
			public _NAME_ getName() {
				return name;
			}
			public void setRank(_RANK_ rank) {
				this.rank = rank;
			}
			public _RANK_ getRank() {
				return rank;
			}
			public void setHighest(_SCORE_ highest) {
				this.highest = highest;
			}
			public _SCORE_ getHighest() {
				return highest;
			}
			public void setHighestDate(_DATE_ highestDate) {
				this.highestDate = highestDate;
			}
			public _DATE_ setHighestDate() {
				return highestDate;
			}
		}
		public static class PersonalRecord extends PersonalRecordTemplate<
			/**_NAME_**/String, 
			/**_RANK_**/Long, 
			/**_SCORE_**/Integer, 
			/**_DATE_**/Date
		> {
			public PersonalRecord(ScoreEntry entry, UserProfile profile) {
				this.name = profile.name;
				this.rank = entry.rank;
				this.highest = entry.score;
				this.highestDate = entry.scoreDate;
			}
		}
	}
	
}
